---
id: 5a23c84252665b21eecc8038
title: Subleq
challengeType: 1
forumTopicId: 302328
dashedName: subleq
---

# --description--

Subleq є прикладом комп’ютера з одним набором команд.

Сама назва походить від єдиної команди: **SU**btract and **B**ranch if **L**ess than or **EQ**ual to zero (укр. відняти і перейти, якщо результат менший або дорівнює нулю).

Ваше завдання — створити інтерпретатор, який емулює таку машину.

Пам’ять машини складається з масиву цілих чисел зі знаком. Підходить будь-який розмір слова, але пам’ять має зберігати як від’ємні, так і додатні числа.

Виконання починається з покажчика команд, спрямованого на перше слово, яке має адресу 0. Воно відбувається наступним чином:

<ol>
  <li>Нехай A, B та C будуть значеннями, збереженими в трьох послідовних словах в пам’яті, починаючи з покажчика команд.</li>
  <li>Перемістіть покажчик команд на 3 слова, щоб він вказував на адресу після тієї, що містить C.</li>
  <li>Якщо A дорівнює -1, то зі стандартного вводу зчитується символ, а його кодова точка зберігається за адресою, вказаною B. C не використовується.</li>
  <li>Якщо B дорівнює -1, то число, яке міститься за адресою, вказаною A, інтерпретується як кодова точка, і виводиться відповідний символ. C знову не використовується.</li>
  <li>В іншому випадку A та B розглядаються як адреси місць в пам’яті. Число, яке міститься за адресою, вказаною A, віднімається від числа за адресою, вказаною B (а результат зберігається за адресою B). Якщо результат дорівнює нулю або є від’ємним, то значення C стає новим покажчиком команд.</li>
  <li>Якщо покажчик команд стає від’ємним, то виконання зупиняється.</li>
</ol>

Інші від’ємні адреси (окрім -1) можна розглядати як еквівалентні -1 або викликати помилку, якщо це доцільно.

Ваш розв’язок має приймати програму для виконання на машині окремо від вводу, який надається програмі самостійно.

Ця програма має бути в звичайному машинному коді subleq: десяткові числа, розділені пропусками, без символьних назв або інших розширень на рівні мови асемблера, які будуть завантажені в пам’ять, починаючи з адреси 0. Покажіть вивід свого розв’язку, коли виконується "Hello, world!". (Зауважте, що цей приклад передбачає ASCII або його надмножину, наприклад, будь-який з наборів символів Latin-N або Unicode. Ви можете перекласти його на інший набір символів, якщо ваша реалізація виконується в несумісному з ASCII середовищі.)

<pre>15 17 -1 17 -1 -1 16 1 -1 16 3 -1 15 15 0 0 -1 72 101 108 108 111 44 32 119 111 114 108 100 33 10 0</pre>

Що в гіпотетичній мові асемблера відповідає чомусь подібному:

<pre>start:
    zero, message, -1
    message, -1, -1
    neg1, start+1, -1
    neg1, start+3, -1
    zero, zero, start
zero: 0
neg1: -1
message: "Hello, world!\n\0"
</pre>

# --instructions--

Напишіть функцію, яка приймає масив цілих чисел як параметр. Це представляє елементи пам’яті. Функція має інтерпретувати послідовність та повернути вихідний рядок. Для цього завдання припустимо, що стандартного вводу немає.

# --hints--

`Subleq` має бути функцією.

```js
assert(typeof Subleq == 'function');
```

`Subleq([15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 0])` має повернути рядок.

```js
assert(
  typeof Subleq([
    15,
    17,
    -1,
    17,
    -1,
    -1,
    16,
    1,
    -1,
    16,
    3,
    -1,
    15,
    15,
    0,
    0,
    -1,
    72,
    101,
    108,
    108,
    111,
    44,
    32,
    119,
    111,
    114,
    108,
    100,
    33,
    0
  ]) == 'string'
);
```

`Subleq([15, 17, -1, 17, -1, -1, 16, 1, -1, 16, 3, -1, 15, 15, 0, 0, -1, 72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 0])` має повернути `"Hello, world!"`.

```js
assert.equal(
  Subleq([
    15,
    17,
    -1,
    17,
    -1,
    -1,
    16,
    1,
    -1,
    16,
    3,
    -1,
    15,
    15,
    0,
    0,
    -1,
    72,
    101,
    108,
    108,
    111,
    44,
    32,
    119,
    111,
    114,
    108,
    100,
    33,
    0
  ]),
  'Hello, world!'
);
```

# --seed--

## --seed-contents--

```js
function Subleq(mem) {

}
```

# --solutions--

```js
function Subleq(mem) {
  var out = '';
  var instructionPointer = 0;
  do {
    var a = mem[instructionPointer];
    var b = mem[instructionPointer + 1];
    if (a === -1) {
    } else if (b === -1) {
      out += String.fromCharCode(mem[a]);
    } else {
      mem[b] -= mem[a];
      if (mem[b] < 1) {
        instructionPointer = mem[instructionPointer + 2];
        continue;
      }
    }
    instructionPointer += 3;
  } while (instructionPointer >= 0);

  return out;
}
```
